#include <stdio.h>
#include "settings.h"

typedef struct {
  unsigned long wrms1;
  unsigned long wrms2;
} WattSample; 

WattSample sample;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  clearWattSample();
  
  // パワーライン1と2の電力計測
  calcWatt();
  
  // シリアル出力をおこなう
  postDenbunMeasurement();
}

void postDenbunMeasurement()
{
  int i;
  byte buff[13];
  unsigned long tmpBcc = 0;
  
  buff[0] = 0x02;               // STX
  buff[1] = 0x4D;               // 電文ID('M')
  buff[2] = 0x38 | 0x80;        // 電文サイズ
  // PowerLine1 電力
  buff[3] = getDenbunByteOfULong(sample.wrms1, 1);
  buff[4] = getDenbunByteOfULong(sample.wrms1, 2);
  buff[5] = getDenbunByteOfULong(sample.wrms1, 3);
  buff[6] = getDenbunByteOfULong(sample.wrms1, 4);
  // PowerLine2 電力
  buff[7] = getDenbunByteOfULong(sample.wrms2, 1);
  buff[8] = getDenbunByteOfULong(sample.wrms2, 2);
  buff[9] = getDenbunByteOfULong(sample.wrms2, 3);
  buff[10] = getDenbunByteOfULong(sample.wrms2, 4);
  
  for (i = 1; i < 11; i++)
  {
    tmpBcc += buff[i];
  }
  
  buff[11] = tmpBcc & 0xFF;                  // BCC
  buff[12] = 0x03;                           // ETX
  
  // 13byte分のシリアル出力をおこなう
  Serial.write(buff, 13);
  Serial.flush();
}

void clearWattSample()
{
  sample.wrms1 = 0;
  sample.wrms2 = 0;
}

// long型電文用long型へ変換する
byte getDenbunByteOfLong(long base, int n)
{
  long calBase;
  
  // -2147483648～-134217729までは-134217728に丸める
  if((0x80000000 <= base) || (base <= 0xF7FFFFFF))
  {
    calBase = 0xF8000000;
  }
  // 134217728～2147483647までは134217727に丸める 
  else if((0x08000000 <= base) || (base <= 0x7FFFFFFF))
  {
    calBase = 0x07FFFFFF;
  }
  // 上記の条件に当てはまらなければそのまま
  else 
  {
    calBase = base;
  }
  
  // マイナス値は28ビットの2の補数を作成する
  if(calBase < 0)
  {
    calBase = (~calBase + 1) & 0x0FFFFFFF;
  }
  
  return 0x80 | (calBase >> ((n - 1) * 7));
}

// unsigned long型から電文用long型へ変換する
byte getDenbunByteOfULong(unsigned long base, int n)
{
  return 0x80 | (base >> ((n - 1) * 7)); 
}

// word型(unsigned short型)から電文用word型へ変換する
byte getDenbunByteOfWord(word base, int n)
{
  return 0x80 | (base >> ((n - 1) * 7));
}

